/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.rainbow.xml;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import org.rainbow.annotation.AnnotationUtils;
import org.rainbow.annotation.xml.ChildNode;
import org.w3c.dom.Document;
import org.w3c.dom.Node;

/**
 *
 * @author hironaga
 */
class ChildNodeHandler extends XmlHandleComponent{

    private XmlCommonHandler commonHandler = XmlCommonHandler.getInstance();

    ChildNodeHandler() {}

    void writeElement(Annotation annotation, Method getter, Field field, Object obj,
            Document doc, String xpath, int index, Node parentElement, XmlHandleHelper helper)
                                                            throws IOException {

        //Annotation Content
        ChildNode childNodeAnnt = (ChildNode)annotation;
        String elementName = childNodeAnnt.elementName();

        //Write Child Object
        String childXpath = xpath + "/" +elementName;
        Object childObj;

        try{
            //Method:"getter" invoke: get-property
            childObj = getter.invoke(obj, new Object[0]);
        } catch (InvocationTargetException ex) {
            return;
        } catch (IllegalAccessException ex) {
            return;
        } catch (IllegalArgumentException ex) {
            return;
        } //try-catch

        //Get ChildNode Class Type
        Class<?> childCls = field.getType();

        //If ChildNode Type is Collection
        if(AnnotationUtils.isCollection(childCls)){
            List listObj = (List)childObj;
            for(int i=0; i<listObj.size(); i++){
                Node newElement = commonHandler.appendElement(doc, parentElement, elementName);
                Object listContentObj= listObj.get(i);
                helper.createElement(listContentObj, doc, childXpath, newElement, i);
            }
        }
        else{
            Node newElement = commonHandler.appendElement(doc, parentElement, elementName);
            helper.createElement(childObj, doc, childXpath, newElement, index);
        }
        
    }

    void readElement(Annotation annotation, Method setter, Field field,
                            Object obj, Document doc, String xpath,
                            Node parentElement, XmlHandleHelper helper)
             throws IOException, InstantiationException, IllegalAccessException{

        //Annotation Content
        ChildNode childNodeAnnt = (ChildNode)annotation;
        String elementName = childNodeAnnt.elementName();

        //Get ChildNode Class Type
        Class<?> childCls = field.getType();

        //Read Child Object
        String childXpath = xpath + "/" +elementName;
        Object setObj = null;

        //If ChildNode Type is Collection
        if(AnnotationUtils.isCollection(childCls)){
            childCls = (Class)AnnotationUtils.getCollectionContentType(field);
            setObj = helper.getElementDataList(doc, childXpath, childCls);
        }
        else{
            setObj = helper.getElementData(doc, childXpath, childCls);
        }

        try {
            //Method:"setter" invoke: set-property
            setter.invoke(obj, new Object[]{ setObj } );
        } catch (IllegalArgumentException ex) {
        } catch (InvocationTargetException ex) {
        } finally{
            return;
        }//try-catch
    }

    void overwriteElement(Annotation annotation, Method getter,
            Field field, Object obj, Document doc, String xpath, int index,
            Node parentElement, XmlHandleHelper helper) throws IOException {

        //Annotation Content
        ChildNode childNodeAnnt = (ChildNode)annotation;
        String elementName = childNodeAnnt.elementName();

        //Write Child Object
        String childXpath = xpath + "/" +elementName;
        Object childObj;

        try{
            //Method:"getter" invoke: get-property
            childObj = getter.invoke(obj, new Object[0]);
        } catch (InvocationTargetException ex) {
            return;
        } catch (IllegalAccessException ex) {
            return;
        } catch (IllegalArgumentException ex) {
            return;
        } //try-catch

        //Get ChildNode Class Type
        Class<?> childCls = field.getType();

        //If ChildNode Type is Collection
        if(AnnotationUtils.isCollection(childCls)){
            List listObj = (List)childObj;
            for(int i=0; i<listObj.size(); i++){
                Node currentElement = commonHandler.getLastElement(doc, childXpath, elementName, index);
                Object listContentObj= listObj.get(i);
                helper.overwriteElement(listContentObj, doc, childXpath, currentElement, i);
            }
        }
        else{
            Node currentElement = commonHandler.getLastElement(doc, childXpath, elementName, index);
            helper.overwriteElement(obj, doc, childXpath, currentElement, index);
        }
    }

}
